home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / pars7.exe / GRAFPACK.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-02-12  |  14.4 KB  |  578 lines

  1. unit grafpack;
  2. {$F+}
  3. interface
  4.  
  5. uses
  6. {$IFDEF DPMI}
  7.   Dos,Crt,Graph, WinAPI,Realtype;
  8. {$ELSE}
  9.   Dos,Crt,Graph,Realtype;
  10. {$ENDIF}
  11. type
  12.    D3World=record
  13.            xw1,xw2,yw1,yw2,zw1,zw2:float;
  14.            end;
  15.  
  16. var
  17.   TheWorld:D3world;
  18.   xwrot,zwrot:integer;
  19.   basex,basey,basez,frontx,fronty,frontz,viewdist:float;
  20.  Graphdriver,Graphmode,XTextglb,YTextglb,VESA16,xw1glb,xw2glb,yw1glb,
  21.  yw2glb:integer;
  22.  charfeedglb,linefeedglb,lineshiftglb:byte;
  23.  Graphmodeglb,VesaGlb:boolean;
  24.  OldOutput : Text;
  25.  xaglb,xscaleglb,yaglb,yscaleglb:float;
  26.  
  27. Procedure InitGraphic(PathToDriver:string);
  28. {Initializes graphics, Redirects the Write and GoToXY-procedures to
  29. work on the graphics screen.}
  30.  
  31. Procedure LeaveGraphic;
  32. {Restores Crt-mode, leaves graphics mode. Use if you want to
  33. switch between the two modes in one program. Before final termination
  34. you also have to use the CloseGraph-command from the Graph-Unit.}
  35.  
  36. Procedure EnterGraphic;
  37. {Switches from Crt-Mode to graphics-mode, InitGraphic must be called
  38. once before.}
  39.  
  40. procedure GotoXY(X, Y : integer);
  41. { Set the text position }
  42.  
  43. procedure setwindow(x1,y1,size:word);
  44. { Defines drawing area; (x1,y1) is upper left point in *text coordinates*,
  45.  size is the *vertical* extension of the window in textlines. The window
  46.  always comes out square. (Roughly)}
  47.  
  48. procedure setd3world(x1,y1,z1,x2,y2,z2,vdist:float;xrot,zrot:integer);
  49. {defines what area of the "real" 3-d-world should be drawn, from what
  50. distance it should be viewed(vdist) and what angles the camera has
  51. with the x and z-axes (xrot,zrot). The 3d-world is always mapped into a
  52. cube with length 2 in each direction that the camera moves around of,
  53. looking into the center of the cube. It has a fixed viewing angle
  54. (it's an older model with a fixed focal distance). The cube is then
  55. projected to the window defined by setwindow. All drawing commands
  56. are then in terms of 3-D-world coordinates.}
  57.  
  58. procedure rotatex(theta:integer);
  59.  
  60. procedure rotatez(theta:integer);
  61.  
  62. procedure zoomin;
  63.  
  64. procedure zoomout;
  65.  
  66. procedure d3drawpoint(x,y,z:float);
  67.  
  68. procedure d3line(xl1,yl1,zl1,xl2,yl2,zl2:float);
  69.  
  70. procedure drawd3axes(c1,c2,c3:string);
  71.  
  72. {self explaining, the rest}
  73. Implementation
  74.  
  75. function XTextpixel(Xtextglb:byte):word;
  76. begin
  77.   XTextpixel:=(XTextglb-1)*Charfeedglb;
  78. end;
  79.  
  80. function YTextpixel(Ytextglb:byte):word;
  81. begin
  82.   YTextpixel:=(YTextglb-1)*linefeedglb+lineshiftglb;
  83. end;
  84.  
  85. var xchar,ychar:word;
  86.  
  87. procedure DC(c:byte);
  88. var viewport:viewporttype; x,y:word;
  89. begin
  90.   getviewsettings(viewport);
  91.   x:=xtextpixel(xtextglb); y:=ytextpixel(ytextglb);
  92.   setviewport(x,y,x+xchar,y+ychar,true);
  93.   clearviewport;
  94.   outtextxy(0,0,chr(c));
  95.   with viewport do setviewport(x1,y1,x2,y2,clip);
  96. end;
  97.  
  98. function WriteGrafChars(var F : TextRec) : integer;
  99. { Used to output graphics characters through the standard output channel. }
  100. const
  101.   BackSpace = #8;
  102.   LineFeed  = #10;
  103.   Return    = #13;
  104. var
  105.   I : integer;
  106. begin
  107.   with F do
  108.     if Mode = fmOutput then
  109.     begin
  110.       if BufPos > BufEnd then
  111.       begin
  112.         for I := BufEnd to Pred(BufPos) do  { Flush the output buffer }
  113.         begin
  114.           case BufPtr^[I] of
  115.             BackSpace : if XTextGlb > 1 then
  116.                           DEC(XTextGlb);
  117.  
  118.             LineFeed  : if YTextGlb < 25 then
  119.                           INC(YTextGlb);
  120.  
  121.             Return    : XTextGlb := 1;
  122.           else
  123.             DC(ORD(BufPtr^[I]));
  124.             if XTextGlb < 80 then
  125.               INC(XTextGlb);
  126.           end; { case }
  127.         end; { for }
  128.       end;
  129.       BufPos := BufEnd;
  130.     end; { if }
  131.   WriteGrafChars := 0;
  132. end; { WriteGrafChars }
  133.  
  134. function GrafCharZero(var F : TextRec) : integer;
  135. { Called when standard output is opened and closed }
  136. begin
  137.   GrafCharZero := 0;
  138. end; { GrafCharZero }
  139.  
  140.  
  141. procedure GrafCharsON;
  142. { Redirects standard output to the WriteGrafChars function. }
  143. begin
  144.   Move(Output, OldOutput, SizeOf(Output));  { Save old output channel }
  145.   with TextRec(Output) do
  146.   begin
  147.     OpenFunc:=@GrafCharZero;       { no open necessary }
  148.     InOutFunc:=@WriteGrafChars;    { WriteGrafChars gets called for I/O }
  149.     FlushFunc:=@WriteGrafChars;    { WriteGrafChars flushes automatically }
  150.     CloseFunc:=@GrafCharZero;      { no close necessary }
  151.     Name[0]:=#0;
  152.   end;
  153. end; { GrafCharsON }
  154.  
  155. procedure GrafCharsOFF;
  156. { Restores original output I/O channel }
  157. begin
  158.   Move(OldOutput, Output, SizeOf(OldOutput));
  159. end; { GrafCharsOFF }
  160.  
  161. procedure GotoXY{(X, Y : integer)};
  162. { Set the text position }
  163. begin
  164.   if (X >= 1) and (X <= 80) and    { Ignore illegal values }
  165.      (Y >= 1) and (Y <= 25) then
  166.   begin
  167.     if GraphModeGlb then
  168.       begin
  169.         XTextGlb := X;      { Set text postion in graphics mode }
  170.         YTextGlb := Y;
  171.       end
  172.     else
  173.       Crt.GotoXY(X, Y);     { Set cursor position in text mode }
  174.   end;
  175. end; { GotoXY }
  176.  
  177.  
  178. type
  179.   VgaInfoBlock = record
  180.     VESASignature: array[0..3] of Byte;
  181.     VESAVersion: Word;
  182.     OEMStringPtr: Pointer;
  183.     Capabilities: array[0..3] of Byte;
  184.     VideoModePtr: Pointer;
  185.   end;
  186.  
  187. const
  188.   VESA16Modes: array[0..2] of Word =
  189.     ($0102, $0104, $0106);
  190.  
  191. { Scan the supported mode table for the highest mode this card
  192.   will provide
  193. }
  194.  
  195. function GetHighestCap(Table: Pointer; Modes: Word; Size: Integer): Integer;
  196.   near; assembler;
  197. asm
  198.         XOR     AX,AX
  199.         LES     DI, Table
  200. @@1:
  201.         MOV     SI, Modes
  202.         ADD     SI, Size
  203.         ADD     SI, Size
  204.         MOV     BX, ES:[DI]
  205.         CMP     BX, 0FFFFH
  206.         JE      @@4
  207.         INC     DI
  208.         INC     DI
  209.         MOV     CX,Size
  210. @@2:
  211.         CMP     BX,[SI]
  212.         JZ      @@3
  213.         DEC     SI
  214.         DEC     SI
  215.         LOOP    @@2
  216. @@3:
  217.         CMP     AX,CX
  218.         JA      @@1
  219.         MOV     AX,CX
  220.         JMP     @@1
  221. @@4:
  222. end;
  223.  
  224. {$IFDEF DPMI}
  225. type
  226.   TRealRegs = record
  227.     RealEDI, RealESI, RealEBP, Reserved, RealEBX,
  228.     RealEDX, RealECX, RealEAX: Longint;
  229.     RealFlags, RealES, RealDS, RealFS, RealGS,
  230.     RealIP, RealCS, RealSP, RealSS: Word;
  231.   end;
  232.  
  233. function DetectVesa16: Integer; far; assembler;
  234. var
  235.   Segment, Selector, VesaCap: Word;
  236. asm
  237. {$IFOPT G+}
  238.         PUSH    0000H
  239.         PUSH    0100H
  240. {$ELSE}
  241.         XOR     AX,AX
  242.         PUSH    AX
  243.         INC     AH
  244.         PUSH    AX
  245. {$ENDIF}
  246.         CALL    GlobalDosAlloc
  247.         MOV     Segment,DX
  248.         MOV     Selector,AX
  249.         MOV     DI,OFFSET RealModeRegs
  250.         MOV     WORD PTR [DI].TRealRegs.RealSP, 0
  251.         MOV     WORD PTR [DI].TRealRegs.RealSS, 0
  252.         MOV     WORD PTR [DI].TRealRegs.RealEAX, 4F00H
  253.         MOV     WORD PTR [DI].TRealRegs.RealES, DX
  254.         MOV     WORD PTR [DI].TRealRegs.RealEDI, 0
  255.         MOV     AX,DS
  256.         MOV     ES,AX
  257.         MOV     AX,0300H
  258.         MOV     BX,0010H
  259.         XOR     CX,CX
  260.         INT     31H
  261.         MOV     DI,OFFSET RealModeRegs
  262.         MOV     AX,grError
  263.         PUSH    AX
  264.         CMP     WORD PTR [DI].TRealRegs.RealEAX,004FH
  265.         JNZ     @@Exit
  266.         POP     AX
  267.         MOV     ES,Selector
  268.         XOR     DI,DI
  269.         CMP     ES:[DI].VgaInfoBlock.VESASignature.Word[0], 'EV'
  270.         JNZ     @@Exit
  271.         CMP     ES:[DI].VgaInfoBlock.VESASignature.Word[2], 'AS'
  272.         JNZ     @@Exit
  273.         MOV     AX,0000
  274.         MOV     CX,1
  275.         INT     31H
  276.         MOV     VesaCap,AX
  277.         MOV     DX,ES:[DI].VgaInfoBlock.VideoModePtr.Word[2]
  278.         MOV     CX,4
  279.         XOR     AX,AX
  280. @@Convert:
  281.         SHL     DX,1
  282.         RCL     AX,1
  283.         LOOP    @@Convert
  284.         ADD     DX,ES:[DI].VgaInfoBlock.VideoModePtr.Word[0]
  285.         ADC     AX,0
  286.         MOV     CX,AX
  287.         MOV     BX,VesaCap
  288.         MOV     AX,0007H
  289.         INT     31H
  290.         INC     AX
  291.         XOR     CX,CX
  292.         MOV     DX,0FFFFH
  293.         INT     31H
  294.         MOV     ES,BX
  295.         PUSH    ES
  296.         PUSH    DI
  297. {$IFOPT G+}
  298.         PUSH    OFFSET Vesa16Modes
  299.         PUSH    0003H
  300. {$ELSE}
  301.         MOV     SI, OFFSET Vesa16Modes
  302.         PUSH    SI
  303.         MOV     AX, 5
  304.         PUSH    AX
  305. {$ENDIF}
  306.         CALL    GetHighestCap
  307.         PUSH    AX
  308.         MOV     BX,VesaCap
  309.         MOV     AX,0001H
  310.         INT     31H
  311. @@Exit:
  312.         PUSH    Selector
  313.         CALL    GlobalDosFree
  314.         POP     AX
  315. end;
  316. {$ELSE}
  317. function DetectVesa16: Integer; far; assembler;
  318. var
  319.   VesaInfo: array[0..255] of Byte;
  320. asm
  321.         MOV     AX,SS
  322.         MOV     ES,AX
  323.         LEA     DI,VesaInfo
  324.         MOV     AX,4F00H
  325.         INT     10H
  326.         CMP     AX,004FH
  327.         MOV     AX,grError
  328.         JNZ     @@Exit
  329.         CMP     ES:[DI].VgaInfoBlock.VESASignature.Word[0], 'EV'
  330.         JNZ     @@Exit
  331.         CMP     ES:[DI].VgaInfoBlock.VESASignature.Word[2], 'AS'
  332.         JNZ     @@Exit
  333.         LES     DI,ES:[DI].VgaInfoBlock.VideoModePtr
  334.         PUSH    ES
  335.         PUSH    DI
  336.         MOV     AX, OFFSET Vesa16Modes
  337.         PUSH    AX
  338.         MOV     AX,3
  339.         PUSH    AX
  340.         CALL    GetHighestCap
  341. @@Exit:
  342. end;
  343. {$ENDIF}
  344.  
  345. procedure initgraphic;
  346. var error:word;
  347. begin
  348.   vesaglb:=false;
  349.   VESA16:=InstallUserDriver('VESA16',@DetectVesa16);
  350.   if GraphResult<>0 then begin
  351.     writeln('Error installing Vesa16'); end;
  352.   GraphDriver := Detect;
  353.   InitGraph(GraphDriver, GraphMode, pathtodriver);
  354.   if GraphResult <> grOk then
  355.   begin
  356.     Writeln('Graphics init error: ', GraphErrorMsg(GraphDriver));
  357.     Halt(1);
  358.   end;
  359.   xchar:=7; ychar:=7;
  360.   Case Graphdriver of
  361.     CGA:begin Charfeedglb:=8; Linefeedglb:=8; Lineshiftglb:=0;
  362.               end;
  363.     EGA:begin Charfeedglb:=8;  Linefeedglb:=14;
  364.                lineshiftglb:=3;
  365.                end;
  366.     EGA64:begin Charfeedglb:=8;  Linefeedglb:=14;
  367.                  LineshiftGlb:=3;
  368.                  end;
  369.     EGAMono:begin Charfeedglb:=8;  Linefeedglb:=14;
  370.                    Lineshiftglb:=3;
  371.                    end;
  372.     HercMono:begin Charfeedglb:=9;  Linefeedglb:=14;
  373.                    LineshiftGlb:=3;
  374.                    end;
  375.     VGA:begin Charfeedglb:=8;  Linefeedglb:=19;
  376.               Lineshiftglb:=3;
  377.               end;
  378.   else
  379.     begin
  380.       vesaglb:=true;
  381.       graphmode:=0;
  382.       setgraphmode(graphmode);
  383.       charfeedglb:=10; linefeedglb:=24;
  384.       lineshiftglb:=8; xchar:=7; ychar:=7;
  385.     end;
  386.   end;
  387.   Graphmodeglb:=true;
  388.   Grafcharson;
  389. end;
  390.  
  391. procedure leavegraphic;
  392. begin
  393.   RestoreCrtMode;
  394.   GraphmodeGlb:=false;
  395.   Grafcharsoff;
  396. end;
  397.  
  398. procedure entergraphic;
  399. begin
  400.   SetGraphmode(graphmode);
  401.   Graphmodeglb:=true;
  402.   GrafCharsOn;
  403. end;
  404.  
  405. procedure setwindow;
  406. begin
  407.   xw1glb:=(x1-1)*charfeedglb; yw1glb:=(y1-1)*linefeedglb;
  408.   yw2glb:= yw1glb+size*linefeedglb;
  409.   xw2glb:=xw1glb+round(0.75*getmaxx/getmaxy*(yw2glb-yw1glb));
  410.   setviewport(xw1glb,yw1glb,xw2glb,yw2glb,true);
  411. end;
  412.  
  413. var thetax,thetaz,sinx,sinz,cosx,cosz:float;
  414.     rightx, rightz:integer;
  415.  
  416. procedure makeradians;
  417. begin
  418.   thetax:=2*pi*xwrot/360; thetaz:=2*pi*zwrot/360;
  419.   sinx:=sin(thetax); cosx:=cos(thetax);
  420.   sinz:=sin(thetaz); cosz:= cos(thetaz);
  421.   rightx:=(xwrot+90) mod 180;  rightz:=zwrot mod 180;
  422. end;
  423.  
  424. function scalar(xb,yb,zb:float):float;
  425. begin
  426.   scalar:=yb*sinx*sinz+zb*cosz+xb*sinz*cosx;
  427. end;
  428.  
  429. procedure initworld;
  430. var umin,umax,vmin,vmax,d2world:float;
  431.     i,j,k:integer;
  432. begin
  433.   makeradians;
  434.   if viewdist<0 then viewdist:=0.00001;
  435.   d2world:=0.25;
  436.   xaglb:=(xw2glb-xw1glb)/2;
  437.   xscaleglb:=(xw2glb-xw1glb)/2/d2world;
  438.   yaglb:=(yw2glb-yw1glb)/2;
  439.   yscaleglb:=(yw2glb-yw1glb)/2/d2world;
  440. end;
  441.  
  442. procedure setd3world(x1,y1,z1,x2,y2,z2,vdist:float;xrot,zrot:integer);
  443. var d:float;
  444. begin
  445.   with theworld do
  446.   begin
  447.     xw1:=x1;  xw2:=x2;  yw1:=y1; yw2:=y2; zw1:=z1;  zw2:=z2;
  448.   end;
  449.   zwrot:=zrot; xwrot:=xrot;  viewdist:=vdist;
  450.   initworld;
  451. end;
  452.  
  453. procedure rotatez(theta:integer);
  454. begin
  455.     zwrot:=zwrot+theta;  initworld;
  456. end;
  457.  
  458. procedure rotatex(theta:integer);
  459. begin
  460.     xwrot:=xwrot+theta;  initworld;
  461. end;
  462.  
  463. procedure zoomin;
  464. var v:float;
  465. begin
  466.   viewdist:=viewdist-0.05; initworld;
  467. end;
  468.  
  469. procedure zoomout;
  470. begin
  471.   viewdist:=viewdist+0.05; initworld;
  472. end;
  473.  
  474. procedure blockx(x:float;var xb:float);
  475. begin
  476.   with TheWorld do
  477.   xb:= -1+2*(x-xw1)/(xw2-xw1);
  478. end;
  479. procedure blocky(y:float;var yb:float);
  480. begin
  481.   with TheWorld do
  482.   yb:= -1+2*(y-yw1)/(yw2-yw1);
  483. end;
  484. procedure blockz(z:float;var zb:float);
  485. begin
  486.   with TheWorld do
  487.   zb:= -1+2*(z-zw1)/(zw2-zw1);
  488. end;
  489.  
  490. procedure project(xb,yb,zb:float; var u,v:float;var visible:boolean);
  491. var scal,d:float;
  492. begin
  493.   scal:=scalar(xb,yb,zb);
  494.   d:=viewdist-scal;
  495.   if d<=0.1 then visible:=false else
  496.   begin
  497.     if rightz<>0 then
  498.       v:=(zb-scal*cosz)/sinz
  499.     else
  500.       v:=-(yb*sinx+xb*cosx)/cosz;
  501.     if rightx<>0 then
  502.       u:=(yb+sinx*(v*cosz-scal*sinz))/cosx
  503.     else
  504.       u:=-xb*sinx;
  505.     u:=u/d;
  506.     v:=v/d;
  507.     visible:=(abs(u)<10) and (abs(v)<10);
  508.   end;
  509. end;
  510.  
  511. procedure d3window(x,y,z:float; var xs,ys:integer;var visible:boolean);
  512. var xb,yb,zb,scal,d,u,v:float;
  513. begin
  514.   blockx(x,xb);  blocky(y,yb);  blockz(z,zb);
  515.   project(xb,yb,zb,u,v,visible);
  516.   if visible then
  517.   begin
  518.     xs:=round(u*xscaleglb+xaglb); ys:=round(yaglb-v*yscaleglb);
  519.   end;
  520. end;
  521.  
  522.  
  523. procedure d3drawpoint(x,y,z:float);
  524. var xs,ys:integer; var visible:boolean;
  525. begin
  526.   d3window(x,y,z,xs,ys,visible);
  527.   if visible then  putpixel(xs,ys,getcolor);
  528. end;
  529.  
  530. procedure d3line(xl1,yl1,zl1,xl2,yl2,zl2:float);
  531. var u1,v1,u2,v2:integer; var visible:boolean;
  532. begin
  533.   d3window(xl1,yl1,zl1,u1,v1,visible);
  534.   if visible then
  535.   begin
  536.     d3window(xl2,yl2,zl2,u2,v2,visible);
  537.     if visible then  line(u1,v1,u2,v2);
  538.   end;
  539. end;
  540.  
  541. procedure drawd3axes(c1,c2,c3:string);
  542.  
  543. procedure drawoneaxis(x1,y1,z1,x2,y2,z2:float;c:string);
  544. var norms,wx,wy:float;  visible:boolean;
  545.     xs1,ys1,xs2,ys2:integer; vsx,vsy:float;
  546. begin
  547.   d3line(x1,y1,z1,x2,y2,z2);
  548.   d3window(x1,y1,z1,xs1,ys1,visible);
  549.   if visible then
  550.   begin
  551.   d3window(x2,y2,z2,xs2,ys2,visible);
  552.   if visible then
  553.   begin
  554.   vsx:=(xs2-xs1); vsy:=(ys2-ys1);
  555.   norms:=sqrt(vsx*vsx+vsy*vsy);
  556.   if norms>0 then
  557.   begin
  558.     vsx:=vsx/norms; vsy:=vsy/norms;
  559.     wx:=(-vsx+vsy)/sqrt(2); wy:=(-vsy-vsx)/sqrt(2);
  560.     line(xs2,ys2,xs2+round(5*wx),ys2+round(5*wy));
  561.     wx:=(-vsx-vsy)/sqrt(2); wy:=(-vsy+vsx)/sqrt(2);
  562.     line(xs2,ys2,xs2+round(5*wx),ys2+round(5*wy));
  563.     moveto(xs2-10,ys2-10);
  564.     outtext(c);
  565.   end;
  566.   end;
  567.   end;
  568. end;
  569.  
  570. begin   {******* drawd3axes ******}
  571.   with TheWorld do
  572.   begin
  573.     drawoneaxis(xw1,yw1,zw1,xw2,yw1,zw1,c1);
  574.     drawoneaxis(xw1,yw1,zw1,xw1,yw2,zw1,c2);
  575.     drawoneaxis(xw1,yw1,zw1,xw1,yw1,zw2,c3);
  576.   end;
  577. end;
  578. end.